#ifndef __LCG_FMT_H__
#define __LCG_FMT_H__
/*  日志格式化模块
        1.抽象格式化子项基类
        2.派生不同的格式化子项子类
        3.对格式化规则字符串进行格式化
        4.对格式化规则字符串进行解析初始化格式化子项数组成员

*/
#include "message.hpp"
#include "level.hpp"

#include <memory>
#include <vector>
#include <sstream>
#include <cassert>
#include <ctime>

//使用命名空间防止命名冲突
namespace lcglog{
    //抽象格式化子项基类
    class FormatItem{
        public:
            using ptr = std::shared_ptr<FormatItem>;                  //使用智能指针管理类对象
            virtual void format(std::ostream& out, const LogMsg& msg) = 0;//用于将LogMsg的各个字段格式化到指定out流中
    };
    //派生不同的格式化子项子类：消息，文件名，行号，线程ID,日志等级，日志器名，日期，制表符，换行符，其他
    class MsgFormatItem : public FormatItem{
        public:
            void format(std::ostream& out, const LogMsg& msg) override{
                out << msg._payload;
            }
    };
    class FileFormatItem : public FormatItem{
        public:
            void format(std::ostream& out, const LogMsg& msg) override{
                out << msg._file;
            }
    };
    class LineFormatItem : public FormatItem{
        public:
            void format(std::ostream& out, const LogMsg& msg) override{
                out << msg._line;
            }
    };
    class ThreadFormatItem : public FormatItem{
        public:
            void format(std::ostream& out, const LogMsg& msg) override{
                out << msg._tid;
            }
    };
    class LevelFormatItem : public FormatItem{
        public:
            void format(std::ostream& out, const LogMsg& msg) override{
                out << LogLevel::toString(msg._level);
            }
    };
    class LoggerFormatItem : public FormatItem{
        public:
            void format(std::ostream& out, const LogMsg& msg) override{
                out << msg._logger;
            }
    };
    class TimeFormatItem : public FormatItem{
        public:
            TimeFormatItem(const std::string& fmt = "%H:%M:%S"):_time_fmt(fmt){}
            void format(std::ostream& out, const LogMsg& msg) override{
                struct tm t;
                localtime_r(&msg._ctime, &t);
                char tmp[32] = {0};
                strftime(tmp, 31, _time_fmt.c_str(), &t);
                out<<tmp;
            }
        private:
            std::string _time_fmt;//默认的时间格式是%H:%M:%S
    };
    class TabFormatItem : public FormatItem{
        public:
            void format(std::ostream& out, const LogMsg& msg) override{
                out << '\t';
            }
    };
    class NLineFormatItem : public FormatItem{
        public:
            void format(std::ostream& out, const LogMsg& msg) override{
                out << '\n';
            }
    };
    class OtherFormatItem : public FormatItem{
        public:
            OtherFormatItem(const std::string& str):_str(str){}
            void format(std::ostream& out, const LogMsg& msg) override{
                out << _str;
            }
        private:
            std::string _str;
    };
    /*
        %d:表示日期 子格式{%H:%M:%S}
        %t:表示线程ID
        %c:表示日志器名称
        %f:表示源码文件名
        %l:表示源码行号
        %p:表示日志级别
        %T:表示制表符缩进
        %m:表示主体消息
        %n:表示换行
    */
    class Formatter{
        private:
            //格式化规则字符串
            std::string _pattern;
            //格式化子项数组
            std::vector<FormatItem::ptr> _items;
        public:
            using ptr = std::shared_ptr<Formatter>;//使用智能指针管理Formatter对象

            Formatter(const std::string& pattern="[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n")
            :_pattern(pattern)
            {
                assert(parsePattern());//必须解析字符串成功
            }
            //对msg进行格式化
            std::string format(const LogMsg& msg){
               std::stringstream ss;
               format(ss, msg);
               return ss.str();
            }
            void format(std::ostream& out, const LogMsg& msg){
                 for(auto& item : _items){
                    item->format(out, msg);
                }
            }

        private:
            //对格式化规则字符串进行解析
            bool parsePattern(){
                //1.对格式化规则字符串进行解析
                //abcd%%e[%d{%H:%M:%S}][%p]%T%m%n
                std::vector<std::pair<std::string, std::string>> fmt_order;
                size_t pos = 0;
                std::string key, val;

                while(pos < _pattern.size()){
                    if(_pattern[pos] != '%'){
                        val.push_back(_pattern[pos++]);
                        continue;
                    }
                    //走到这里说明pos位置的字符是%
                    //注意点1：如果这个位置是字符%,要看一下下一个字符是否是%，别问了+1
                    if(pos < _pattern.size() && _pattern[pos+1] == '%'){

                        val.push_back('%');
                        pos += 2;
                        continue;
                    }
                    if(val.empty() == false){
                        fmt_order.push_back(std::make_pair("", val));
                        val.clear();
                    }
                   //走到这里说明pos位置的字符是%,并且后一个字符不是%
                   pos += 1;
                   if(pos == _pattern.size()){
                    std::cout<<"%之后，没有对应的格式化字符!\n";
                    return false;
                   }
                   key = _pattern[pos];
                   pos += 1;
                   if(pos < _pattern.size() && _pattern[pos] == '{'){
                    pos += 1;//指向{之后子规则的起始位置
                    while(pos < _pattern.size() && _pattern[pos] != '}'){
                        val.push_back(_pattern[pos++]);
                    }
                    //走到这里有两种情况 1.没有找到} 2.找到},循环正常结束
                    if(pos == _pattern.size()){
                        std::cout<<"子规则匹配错误{}!\n";
                        return false;
                    }
                    pos += 1;//这时pos指向的是}位置，向后走一步走到了下一次处理的新位置
                   }
                   fmt_order.push_back(std::make_pair(key, val));
                   key.clear();
                   val.clear();
                }
                //2.根据解析得到的数据初始化格式化子项数组成员
                for(auto& item : fmt_order){
                    _items.push_back(createItem(item.first, item.second));
                }
                return true;
            }
            //根据不同的格式化字符创建不同的格式化子项对象
            FormatItem::ptr createItem(const std::string& key, const std::string& val){

                if(key == "d")  return std::make_shared<TimeFormatItem>(val);
                if(key == "t")  return std::make_shared<ThreadFormatItem>();
                if(key == "c")  return std::make_shared<LoggerFormatItem>();
                if(key == "f")  return std::make_shared<FileFormatItem>();
                if(key == "l")  return std::make_shared<LineFormatItem>();
                if(key == "p")  return std::make_shared<LevelFormatItem>();
                if(key == "m")  return std::make_shared<MsgFormatItem>();
                if(key == "n")  return std::make_shared<NLineFormatItem>();
                if(key == "T")  return std::make_shared<TabFormatItem>();
                if(key == "")   return std::make_shared<OtherFormatItem>(val);//匹配其他的格式化字符

                std::cout<<"没有匹配的格式化字符: %"<<key<<std::endl;
                abort();
                return FormatItem::ptr();
            }
            
    };
}

#endif